package cn.uncode.springcloud.gateway.canary;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.ObjectUtils;

import cn.uncode.springcloud.gateway.config.CanaryProperties;
import cn.uncode.springcloud.gateway.ribbon.RibbonContext;
import cn.uncode.springcloud.utils.net.WebUtil;

/**
 * 默认灰度策略，包括ip和参数in request and session
 * 
 * @author juny
 * @date 2019年4月26日
 *
 */
public class DefaultCanaryStrategy implements CanaryStrategy {
	
	private boolean enabled = false;
	
	private Map<String, StrategyModel> StrategyList = new HashMap<>();
	
	private Map<String, String> ip2flag = new HashMap<>();
	
	private Map<String, Set<String>> keyInRequest2value = new HashMap<>();
	
	private Map<String, String> keyInRequest2flag = new HashMap<>();
	
	private Map<String, Set<String>> keyInSession2value = new HashMap<>();
	
	private Map<String, String> keyInSession2flag = new HashMap<>();
	
	public DefaultCanaryStrategy(CanaryProperties canaryProperties) {
		if(!ObjectUtils.isEmpty(canaryProperties)) {
			if(canaryProperties.isEnabled()) {
				this.enabled = true;
				if(null != canaryProperties.getStrategy()) {
					for(StrategyModel item:canaryProperties.getStrategy()) {
						StrategyList.put(item.getFlag(), item);
						if(DEFAULT_STRATEGY_TYPE_IP.equals(item.getType())) {
							Set<String> sets = item.getValue();
							for(String str:sets) {
								ip2flag.put(str, item.getFlag());
							}
						}else if(DEFAULT_STRATEGY_TYPE_REQUEST.equals(item.getType())) {
							keyInRequest2value.put(item.getKey(), item.getValue());
							keyInRequest2flag.put(item.getKey(), item.getFlag());
						}else if(DEFAULT_STRATEGY_TYPE_SESSION.equals(item.getType())) {
							keyInSession2value.put(item.getKey(), item.getValue());
							keyInSession2flag.put(item.getKey(), item.getFlag());
						}
					}
				}
			}
		}
	}
	
	@Override
	public RibbonContext resolve(ServerHttpRequest request) {
		RibbonContext ribbonContext = new RibbonContext();
		if(enabled) {
			String flag = null;
			String ip = request.getRemoteAddress().getAddress().getHostName();
			if(ip2flag.containsKey(ip)) {
				flag = ip2flag.get(ip);
			}else {
				for(Entry<String, Set<String>> item:keyInRequest2value.entrySet()) {
					Object value = WebUtil.getRequest().getParameter(item.getKey());
					if(null != value) {
						String val = String.valueOf(value);
						if(item.getValue().contains(val)) {
							flag = keyInRequest2flag.get(item.getKey());
						}
					}
				}
				for(Entry<String, Set<String>> item:keyInSession2value.entrySet()) {
					Object value = WebUtil.getRequest().getSession().getAttribute(item.getKey());
					if(null != value) {
						String val = String.valueOf(value);
						if(item.getValue().contains(val)) {
							flag = keyInSession2flag.get(item.getKey());
						}
					}
				}
			}
			if(StringUtils.isNotBlank(flag)) {
				ribbonContext.setCanaryFlag(flag);
			}
		}
		return ribbonContext;
	}

	public Map<String, String> getIp2flag() {
		return ip2flag;
	}

	public void setIp2flag(Map<String, String> ip2flag) {
		this.ip2flag = ip2flag;
	}

	public Map<String, Set<String>> getKeyInRequest2value() {
		return keyInRequest2value;
	}

	public void setKeyInRequest2value(Map<String, Set<String>> keyInRequest2value) {
		this.keyInRequest2value = keyInRequest2value;
	}

	public Map<String, String> getKeyInRequest2flag() {
		return keyInRequest2flag;
	}

	public void setKeyInRequest2flag(Map<String, String> keyInRequest2flag) {
		this.keyInRequest2flag = keyInRequest2flag;
	}

	public Map<String, Set<String>> getKeyInSession2value() {
		return keyInSession2value;
	}

	public void setKeyInSession2value(Map<String, Set<String>> keyInSession2value) {
		this.keyInSession2value = keyInSession2value;
	}

	public Map<String, String> getKeyInSession2flag() {
		return keyInSession2flag;
	}

	public void setKeyInSession2flag(Map<String, String> keyInSession2flag) {
		this.keyInSession2flag = keyInSession2flag;
	}
	
	

}
